package com.zatech.cgnci.project.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zatech.cgnci.project.base.context.UserContext;
import com.zatech.cgnci.project.base.enums.ApprovalConfigEnum;
import com.zatech.cgnci.project.base.enums.BusinessScenariosEnum;
import com.zatech.cgnci.project.base.enums.OperationTypeEnum;
import com.zatech.cgnci.project.base.enums.ResponseCodeEnum;
import com.zatech.cgnci.project.base.exception.GlobalException;
import com.zatech.cgnci.project.base.utils.BeanUtils;
import com.zatech.cgnci.project.base.utils.ConvertUtils;
import com.zatech.cgnci.project.base.utils.DateUtils;
import com.zatech.cgnci.project.base.utils.VerifyUtils;
import com.zatech.cgnci.project.dto.*;
import com.zatech.cgnci.project.entity.CgnciApprovalInfoDO;
import com.zatech.cgnci.project.entity.CgnciBusinessInsuranceDO;
import com.zatech.cgnci.project.entity.CgnciRiskDO;
import com.zatech.cgnci.project.entity.UserEntity;
import com.zatech.cgnci.project.mapper.CgnciApprovalInfoMapper;
import com.zatech.cgnci.project.service.*;
import com.zatech.cgnci.project.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 承保管理--保单表 前端控制器
 * </p>
 *
 * @author Generator
 * @since 2024-12-20
 */
@RestController
@RequestMapping("/api/business/divide-out")
@RequiredArgsConstructor
@Api(produces = "application/json", tags = "承保管理--分出合约管理api接口文档")
public class CgnciBusinessDivideOutController {

    private final CgnciBusinessInsuranceService cgnciBusinessInsuranceService;

    private final IApprovalService approvalService;

    private final CgnciApprovalInfoMapper approvalInfoMapper;

    private final CgnciReinsuranceRiskService cgnciReinsuranceRiskService;

    private final CgnciReinsuranceRiskInsuredService cgnciReinsuranceRiskInsuredService;

    private final CgnciOperationLogsService cgnciOperationLogsService;

    private final CgnciRiskService cgnciRiskService;

    @PostMapping("/page")
    @ApiOperation(value = "分页列表查询")
    public IPage<CgnciBusinessInsurancePageVO> page(@RequestBody CgnciBusinessInsuranceQueryDTO queryDTO) {
        queryDTO.setBusinessType("3");
        if (VerifyUtils.isNotEmpty(queryDTO.getPolicyRiskSubTypeCode())) {
            // 查询所有的分出合约
            List<CgnciBusinessInsurancePageVO> list = cgnciBusinessInsuranceService.listBusinessInsurance(queryDTO);
            if (VerifyUtils.isEmpty(list)) {
                return new Page<>();
            }
            list = list.stream().filter(value -> areValuesContainsAll(value.getRiskSubTypeCode(), queryDTO.getPolicyRiskSubTypeCode())).collect(Collectors.toList());
            if (VerifyUtils.isEmpty(list)) {
                return new Page<>();
            }
            Set<Long> insuranceIds = list.stream().map(CgnciBusinessInsuranceDO::getInsuranceId).collect(Collectors.toSet());
            queryDTO.setInsuranceIds(insuranceIds);
        }
        return cgnciBusinessInsuranceService.pageBusinessInsurance(queryDTO);
    }


    @GetMapping("/detail")
    @ApiOperation(value = "详情")
    public CgnciBusinessInsuranceMainVO detail(@RequestParam(value = "insuranceId") @NotNull(message = "insuranceId不能为空") Long insuranceId) {
        return cgnciBusinessInsuranceService.detail(insuranceId, "3");
    }

    @PostMapping("/next/create")
    @ApiOperation(value = "新增录入分出合约-下一步")
    @Transactional(rollbackFor = Exception.class)
    public Long nextCreate(@RequestBody @Valid CgnciBusinessDivideOutNextCreateDTO addCreateDTO) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        CgnciBusinessInsuranceDO businessInsuranceDO = ConvertUtils.convert(addCreateDTO, CgnciBusinessInsuranceDO.class);
        // 第一步先插入业务数据,用来绑定工作量formId formNo,并且关联工作台的跳转地址url以及参数
        businessInsuranceDO.setFormNo(BeanUtils.getUUID());
        // 业务类型-分出合约
        businessInsuranceDO.setBusinessType("3");
        businessInsuranceDO.setCreateUser(user.getNameAndCode());
        businessInsuranceDO.setUpdateUser(user.getNameAndCode());
        cgnciBusinessInsuranceService.save(businessInsuranceDO);

        // 创建任务,绑定工作流formId. 并且关联工作台的跳转地址url以及参数
        ApprovalInfoVO approvalInfoVO = approvalService.create(FlowTaskCreateDTO.builder().approvalConfigGroupId(ApprovalConfigEnum.APPROVAL_CONFIG_013.getGroupId()).formId(String.valueOf(businessInsuranceDO.getInsuranceId())).formNo(businessInsuranceDO.getFormNo())
                .redirectionUrl(ApprovalConfigEnum.APPROVAL_CONFIG_013.getRedirectionUrl()).redirectionParam(String.valueOf(businessInsuranceDO.getInsuranceId())).redirectionDesc(ApprovalConfigEnum.APPROVAL_CONFIG_013.getRedirectionDesc()).build());
        cgnciOperationLogsService.insertOperationLogs(
                String.valueOf(businessInsuranceDO.getInsuranceId()),
                BusinessScenariosEnum.POLICY.getCode(),
                OperationTypeEnum.SUBMIT_OUTGOING_CONTRACT.getCode(),
                "分出合约录入任务号：" + approvalInfoVO.getTaskId(),
                user.getNameAndCode()
        );
        return businessInsuranceDO.getInsuranceId();
    }

    @PostMapping("/check/hyRiskSubTypes")
    @ApiOperation(value = "校验合约层-险种是否均设置分项信息")
    public CheckHyRiskSubTypesVO hyRiskSubTypes(@RequestBody @Valid CheckHyRiskSubTypesDTO checkHyRiskSubTypesDTO) {
        CheckHyRiskSubTypesVO result = CheckHyRiskSubTypesVO.builder().build();
        result.setCheckHyRiskSubTypes(true);
        String[] riskSubTypeCodes = checkHyRiskSubTypesDTO.getRiskSubTypeCodes().split(",");
        for (String riskSubTypeCode : riskSubTypeCodes) {
            List<CheckHyRiskSubTypesDTO.CheckReinsuranceInfoDTO> checkReinsuranceInfo = checkHyRiskSubTypesDTO.getCheckReinsuranceInfo();
            for (CheckHyRiskSubTypesDTO.CheckReinsuranceInfoDTO reinsurance : checkReinsuranceInfo) {
                List<CheckHyRiskSubTypesDTO.CheckReinsuranceRiskDTO> checkRisks = reinsurance.getCheckRisks();
                CheckHyRiskSubTypesDTO.CheckReinsuranceRiskDTO checkReinsuranceRisk =
                        checkRisks.stream().filter(value -> riskSubTypeCode.equals(value.getRiskSubTypeCode())).findFirst().orElse(null);
                if (VerifyUtils.isEmpty(checkReinsuranceRisk)) {
                    result.setCheckHyRiskSubTypes(false);
                    CgnciRiskDO riskDO = cgnciRiskService.getOne(new LambdaQueryWrapper<CgnciRiskDO>().eq(CgnciRiskDO::getRiskSubTypeCode, riskSubTypeCode));
                    result.setMsg("险种{" + riskDO.getRiskSubType() + "}未设置分项信息，确认是否提交");
                    break;
                }
            }
        }
        return result;
    }

    @PostMapping("/saveOrUpdate")
    @ApiOperation(value = "新增或者修改")
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdate(@RequestBody @Valid CgnciBusinessInsuranceSaveOrUpdateDTO updateDTO) {

        CgnciBusinessInsuranceDO businessInsurance = cgnciBusinessInsuranceService.saveOrUpdateBusinessInsurance(updateDTO, "3");

        // 维护业务名称到工作台
        CgnciApprovalInfoDO approvalInfoDO = approvalInfoMapper.selectOne(new LambdaQueryWrapper<CgnciApprovalInfoDO>()
                .eq(CgnciApprovalInfoDO::getFormId, updateDTO.getBusinessInsuranceUpdateDTO().getInsuranceId()));
        if (VerifyUtils.isEmpty(approvalInfoDO)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "任务流程不存在");
        }
        approvalInfoDO.setBusinessName(updateDTO.getBusinessInsuranceUpdateDTO().getBusinessName());
        approvalInfoMapper.updateById(approvalInfoDO);

        // 提交审核
        if (VerifyUtils.isNotEmpty(updateDTO.getFlowTaskType()) && "submit".equals(updateDTO.getFlowTaskType())) {
            // 是否触发倒签
            String groupId = null;
            if (businessInsurance.getCreateTime().after(DateUtils.getTimeByType(updateDTO.getBusinessInsuranceUpdateDTO().getStartDate(), "start"))) {
                groupId = ApprovalConfigEnum.APPROVAL_CONFIG_014.getGroupId();
            }
            if (VerifyUtils.isNotEmpty(groupId)) {
                approvalInfoMapper.updateById(CgnciApprovalInfoDO.builder().approvalInfoId(updateDTO.getApprovalInfoId()).approvalConfigGroupId(groupId).build());
            }
            cgnciBusinessInsuranceService.submit(FlowTaskSubmitDTO.builder().approvalInfoId(updateDTO.getApprovalInfoId()).formId(String.valueOf(businessInsurance.getInsuranceId())).build());
        }
    }

    @PostMapping("/approve")
    @ApiOperation(value = "审核流程任务")
    @Transactional(rollbackFor = Exception.class)
    public void approve(@RequestBody @Valid FlowTaskApprovalDTO flowTaskDTO) {
        cgnciBusinessInsuranceService.approve(flowTaskDTO);
    }

    @GetMapping("/listBackNode")
    @ApiOperation(value = "获取退回流程节点")
    public List<ApprovalConfigVO> listBackNode(@RequestParam(value = "insuranceId") @NotNull(message = "insuranceId不能为空") Long insuranceId) {
        CgnciBusinessInsuranceDO businessInsuranceDO = cgnciBusinessInsuranceService.getById(insuranceId);
        return approvalService.listBackNode(String.valueOf(businessInsuranceDO.getInsuranceId()), businessInsuranceDO.getFormNo());
    }

    @PostMapping("/back")
    @ApiOperation(value = "退回流程任务")
    @Transactional(rollbackFor = Exception.class)
    public void back(@RequestBody @Valid FlowTaskBackDTO flowTaskDTO) {
        cgnciBusinessInsuranceService.back(flowTaskDTO);
    }

    @GetMapping("/signOut")
    @ApiOperation(value = "注销")
    @Transactional(rollbackFor = Exception.class)
    public void signOut(@RequestParam(value = "insuranceId") @NotNull(message = "insuranceId不能为空") Long insuranceId) {
        cgnciBusinessInsuranceService.signOut(insuranceId);
    }

    @GetMapping("/log")
    @ApiOperation(value = "获取操作日志")
    public List<ApprovalRecordVO> log(@RequestParam(value = "insuranceId") @NotNull(message = "insuranceId不能为空") Long insuranceId) {
        return cgnciBusinessInsuranceService.log(insuranceId);
    }

    @GetMapping("/reinsuranceRisk/deleteById")
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "删除合约分出分项险种")
    public void deleteReinsuranceRiskDetailById(@RequestParam(value = "reinsuranceRiskId") @ApiParam(value = "reinsuranceRiskId") Long reinsuranceRiskId) {
        cgnciReinsuranceRiskService.deleteReinsuranceRiskForDivideOut(reinsuranceRiskId);
    }

    @GetMapping("/reinsuranceRisk/deleteByIds")
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "批量删除合约分出分项险种")
    public void deleteReinsuranceRiskDetailByIds(@RequestParam(value = "reinsuranceRiskIds") @ApiParam(value = "reinsuranceRiskIds") String reinsuranceRiskIds) {
        List<Long> idList = Arrays.stream(reinsuranceRiskIds.split(",")).map(Long::valueOf).collect(Collectors.toList());
        idList.forEach(cgnciReinsuranceRiskService::deleteReinsuranceRiskForDivideOut);
    }

    @GetMapping("/reinsuranceRiskInsured/deleteById")
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "删除删除合约分出分项险种标的")
    public void deleteReinsuranceRiskInsuredById(@RequestParam(value = "riskInsuredId") @ApiParam(value = "riskInsuredId") Long riskInsuredId) {
        cgnciReinsuranceRiskInsuredService.deleteReinsuranceRiskInsuredForDivideOut(riskInsuredId);
    }

    @GetMapping("/reinsuranceRiskInsured/deleteByIds")
    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "批量删除删除合约分出分项险种标的")
    public void deleteReinsuranceRiskInsuredByIds(@RequestParam(value = "riskInsuredIds") @ApiParam(value = "riskInsuredIds") String riskInsuredIds) {
        List<Long> idList = Arrays.stream(riskInsuredIds.split(",")).map(Long::valueOf).collect(Collectors.toList());
        idList.forEach(cgnciReinsuranceRiskInsuredService::deleteReinsuranceRiskInsuredForDivideOut);
    }


    private boolean areValuesContainsAll(String riskSubTypeCode, String policyRiskSubTypeCode) {
        // 将字符串按逗号分隔成列表
        List<String> list1 = Arrays.asList(riskSubTypeCode.split(","));
        List<String> list2 = Arrays.asList(removeDuplicates(policyRiskSubTypeCode).split(","));

        // 对列表进行排序
        list1.sort(String::compareTo);
        list2.sort(String::compareTo);

        // list2元素都在list1中
        return new HashSet<>(list1).containsAll(list2);
    }

    /**
     * 同一险种去重
     */
    private String removeDuplicates(String input) {
        return Arrays.stream(input.split(","))
                .distinct()
                .collect(Collectors.joining(","));
    }

}

